package com.software.audiorecorddemo

import android.Manifest
import android.content.pm.PackageManager
import android.media.AudioFormat
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

class MainActivity : AppCompatActivity(), AudioCapture.AudioCaptureCallback {
    private val TAG = "AudioRecordDemo"
    private val REQUEST_PERMISSION_CODE = 1000

    // 是否正在录制
    private var isRecording = false
    // UI组件
    private lateinit var tvStatus: TextView
    private lateinit var btnStartRecord: Button
    private lateinit var btnStopRecord: Button
    private lateinit var btnPlayRecord: Button

    // 音频采集器
    private var audioCapture: AudioCapture? = null
    
    // 配置
    private val sampleRate = 44100    // 采样率 44.1KHz
    private val channels = 1          // 单声道
    private val audioFormat = AudioFormat.ENCODING_PCM_16BIT  // 16位PCM格式

    // 文件路径
    private lateinit var pcmFilePath: String
    private lateinit var aacFilePath: String
    private lateinit var audioFolder: String
    
    // PCM文件写入
    private var pcmOutputStream: FileOutputStream? = null

    // 播放器
    private var mediaPlayer: MediaPlayer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化UI组件
        tvStatus = findViewById(R.id.tvStatus)
        btnStartRecord = findViewById(R.id.btnStartRecord)
        btnStopRecord = findViewById(R.id.btnStopRecord)
        btnPlayRecord = findViewById(R.id.btnPlayRecord)

        // 初始化文件路径
        audioFolder = getExternalFilesDir(Environment.DIRECTORY_MUSIC)?.absolutePath ?: ""
        pcmFilePath = "$audioFolder/audio_record_demo.pcm"
        aacFilePath = "$audioFolder/audio_record_demo.aac"

        // 初始化音频采集器
        audioCapture = AudioCapture(
            context = this,
            callback = this,
            sampleRate = sampleRate,
            channels = channels,
            audioFormat = audioFormat
        )

        // 设置按钮点击事件
        btnStartRecord.setOnClickListener {
            startRecordWithPermissionCheck()
        }

        btnStopRecord.setOnClickListener {
            stopRecording()
        }

        btnPlayRecord.setOnClickListener {
            playRecording()
        }
        
        // 初始状态
        updateUI(false)
    }

    private fun startRecordWithPermissionCheck() {
        Log.d(TAG, "开始权限检查")
        
        // 检查录音权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            Log.d(TAG, "录音权限未授予，请求权限")
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.RECORD_AUDIO),
                REQUEST_PERMISSION_CODE
            )
        } else {
            Log.d(TAG, "录音权限已授予，开始录音")
            startRecording()
        }
        
        // 单独检查存储权限，但不阻止录音
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE
                ),
                REQUEST_PERMISSION_CODE + 1
            )
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_PERMISSION_CODE) {
            // 检查是否包含录音权限，以及是否被授予
            val audioPermissionIndex = permissions.indexOf(Manifest.permission.RECORD_AUDIO)
            if (audioPermissionIndex != -1 && grantResults.getOrNull(audioPermissionIndex) == PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "录音权限已通过权限请求授予")
                startRecording()
            } else {
                Log.d(TAG, "录音权限请求被拒绝")
                Toast.makeText(this, "需要录音权限才能继续", Toast.LENGTH_SHORT).show()
                tvStatus.text = "录音权限被拒绝"
            }
        }
    }
    
    /**
     * 开始录音
     */
    private fun startRecording() {
        try {
            // 删除已有文件
            if (File(pcmFilePath).exists()) {
                File(pcmFilePath).delete()
            }
            if (File(aacFilePath).exists()) {
                File(aacFilePath).delete()
            }

            // 创建PCM文件输出流
            pcmOutputStream = FileOutputStream(pcmFilePath)
            
            // 开始录音
            val success = audioCapture?.startRecording() ?: false
            if (success) {
                isRecording = true
                updateUI(true)
                Log.d(TAG, "开始录音")
            } else {
                Log.e(TAG, "开始录音失败")
                Toast.makeText(this, "开始录音失败", Toast.LENGTH_SHORT).show()
                pcmOutputStream?.close()
                pcmOutputStream = null
            }
        } catch (e: Exception) {
            Log.e(TAG, "录音异常: ${e.message}")
            Toast.makeText(this, "录音异常: ${e.message}", Toast.LENGTH_SHORT).show()
            pcmOutputStream?.close()
            pcmOutputStream = null
        }
    }

    /**
     * 停止录音
     */
    private fun stopRecording() {
        try {
            isRecording = false
            
            // 停止录音并清理
            audioCapture?.stopRecording()
            
            // 关闭PCM文件流
            pcmOutputStream?.close()
            pcmOutputStream = null
            
            // 转换PCM到AAC
            convertPcmToAac()
            
            updateUI(false)
            Log.d(TAG, "停止录音")
        } catch (e: Exception) {
            Log.e(TAG, "停止录音异常: ${e.message}")
            Toast.makeText(this, "停止录音异常: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
    
    /**
     * 播放录音
     */
    private fun playRecording() {
        try {
            val aacFile = File(aacFilePath)
            if (!aacFile.exists()) {
                Toast.makeText(this, "录音文件不存在", Toast.LENGTH_SHORT).show()
                return
            }
            
            // 停止当前播放
            mediaPlayer?.release()
            
            // 创建并配置新的播放器
            mediaPlayer = MediaPlayer().apply {
                setDataSource(aacFilePath)
                prepare()
                setOnCompletionListener {
                    Toast.makeText(this@MainActivity, "播放完成", Toast.LENGTH_SHORT).show()
                }
                start()
            }
            
            Toast.makeText(this, "开始播放", Toast.LENGTH_SHORT).show()
        } catch (e: Exception) {
            Log.e(TAG, "播放异常: ${e.message}")
            Toast.makeText(this, "播放异常: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
    
    /**
     * 将PCM文件转换为AAC文件
     */
    private fun convertPcmToAac() {
        try {
            val pcmFile = File(pcmFilePath)
            if (!pcmFile.exists()) {
                Log.e(TAG, "PCM文件不存在")
                return
            }
            
            val pcmByteCount = pcmFile.length().toInt()
            
            // 如果录音时长太短，可能无法生成有效AAC文件
            if (pcmByteCount < 100) {
                Log.e(TAG, "录音时长太短")
                Toast.makeText(this, "录音时长太短", Toast.LENGTH_SHORT).show()
                return
            }
            
            // 使用AudioProcessor将PCM转为AAC
            val result = AudioProcessor.pcmToAac(
                pcmFile = pcmFile,
                aacFile = File(aacFilePath),
                sampleRate = sampleRate,
                channels = channels,
                bitRate = 96000 // 96Kbps
            )
            
            if (result) {
                Toast.makeText(this, "AAC文件已保存至: $aacFilePath", Toast.LENGTH_SHORT).show()
                Log.d(TAG, "AAC文件已保存: $aacFilePath")
            } else {
                Toast.makeText(this, "AAC文件生成失败", Toast.LENGTH_SHORT).show()
                Log.e(TAG, "AAC文件生成失败")
            }
        } catch (e: Exception) {
            Log.e(TAG, "PCM转AAC异常: ${e.message}")
            Toast.makeText(this, "PCM转AAC异常: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
    
    /**
     * 更新UI状态
     */
    private fun updateUI(recording: Boolean) {
        btnStartRecord.isEnabled = !recording
        btnStopRecord.isEnabled = recording
        btnPlayRecord.isEnabled = !recording && File(aacFilePath).exists()
        
        tvStatus.text = if (recording) "正在录音..." else "就绪"
    }
    
    /**
     * 收到音频数据回调
     * 实现AudioCapture.AudioCaptureCallback接口
     */
    override fun onAudioDataAvailable(data: ByteArray) {
        try {
            if (isRecording && pcmOutputStream != null) {
                pcmOutputStream?.write(data)
            }
        } catch (e: IOException) {
            Log.e(TAG, "写入PCM数据异常: ${e.message}")
        }
    }
    
    /**
     * 录音开始回调
     * 实现AudioCapture.AudioCaptureCallback接口
     */
    override fun onRecordingStarted() {
        runOnUiThread {
            tvStatus.text = "正在录音..."
            updateUI(true)
        }
    }

    /**
     * 录音停止回调
     * 实现AudioCapture.AudioCaptureCallback接口
     */
    override fun onRecordingStopped() {
        runOnUiThread {
            tvStatus.text = "录音结束"
            updateUI(false)
        }
    }
    
    override fun onError(error: String) {
        Log.e(TAG, "音频采集错误: $error")
        runOnUiThread {
            Toast.makeText(this, "音频采集错误: $error", Toast.LENGTH_SHORT).show()
            if (isRecording) {
                stopRecording()
            }
        }
    }
    
    override fun onDestroy() {
        if (isRecording) {
            stopRecording()
        }
        
        mediaPlayer?.release()
        mediaPlayer = null
        
        super.onDestroy()
    }
}